#include <stdint.h>
#include "../sign.h"
#include "../poly.h"
#include "../polyvec.h"
#include "../params.h"
#include "cpucycles.h"
#include "speed_print.h"
#include "../smallntt.h"
#include "../smallpoly.h"
#include "../lowram.h"

#define NTESTS 100000

uint64_t t[NTESTS];

void compare_sm_sb()
{
  unsigned int i;
  uint8_t seed[CRHBYTES];
  uint8_t ccomp[68];
  uint8_t s1bytes[POLYETA_PACKEDBYTES];
  uint8_t pk[CRYPTO_PUBLICKEYBYTES];
  uint8_t sk[CRYPTO_SECRETKEYBYTES];
  poly r, a, c;
  smallpoly scp, sp;

  crypto_sign_keypair(pk, sk);
  poly_challenge(&c, seed);
  poly_challenge_compress(ccomp, &c);

  for (i = 0; i < NTESTS; i++)
  {
    t[i] = cpucycles();
    
    poly_small_ntt_copy(&scp, &c);
    unpack_sk_s1(&sp, sk, 0);
    small_ntt(sp.coeffs);
    poly_small_basemul_invntt(&r, &scp, &sp);
  }
  print_results("small ntt mul (cs):", t, NTESTS);


  for (i = 0; i < NTESTS; i++)
  {
    t[i] = cpucycles();
    
    poly_schoolbook(&r, ccomp, sk + SEEDBYTES + TRBYTES + SEEDBYTES +
      L*POLYETA_PACKEDBYTES + K*POLYETA_PACKEDBYTES + 1*POLYT0_PACKEDBYTES);
  }
  print_results("schoolbook mul (ct0):", t, NTESTS);
  
  poly_small_ntt_copy(&scp, &c);
}

void KeccakF1600_StatePermute(uint64_t state[25]);
int main(void)
{
  unsigned int i;
  size_t siglen;
  uint8_t pk[CRYPTO_PUBLICKEYBYTES];
  uint8_t sk[CRYPTO_SECRETKEYBYTES];
  uint8_t sig[CRYPTO_BYTES];
  // polyvecl mat[K];
  // poly *a = &mat[0].vec[0];
  // poly *b = &mat[0].vec[1];
  // poly *c = &mat[0].vec[2];
  // keccak_state state;

  compare_sm_sb();

  // for(i = 0; i < NTESTS; ++i) {
  //   t[i] = cpucycles();
  //   poly_uniform_gamma1(a, seed, 0);
  // }
  // print_results("poly_uniform_gamma1:", t, NTESTS);

  for(i = 0; i < NTESTS; ++i) {
    t[i] = cpucycles();
    crypto_sign_keypair(pk, sk);
  }
  print_results("Keypair:", t, NTESTS);

  for(i = 0; i < NTESTS; ++i) {
    t[i] = cpucycles();
    crypto_sign_signature(sig, &siglen, sig, CRHBYTES, NULL, 0, sk);
  }
  print_results("Sign:", t, NTESTS);

  for(i = 0; i < NTESTS; ++i) {
    t[i] = cpucycles();
    crypto_sign_verify(sig, CRYPTO_BYTES, sig, CRHBYTES, NULL, 0, pk);
  }
  print_results("Verify:", t, NTESTS);

  return 0;
}
